#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>

#include "imbus_internal.h"
#include "im_value_impl.h"


IMBool
__im_value_impl_serialize (const IMValueImpl *impl, IMStream *sp)
{
    switch (impl->type) {
        case IM_TYPE_INVALID:
            return im_stream_put_void (sp);
        case IM_TYPE_CHAR:
            return im_stream_put_char (sp, (IMChar) impl->data.v_int32);
        case IM_TYPE_UCHAR:
            return im_stream_put_uchar (sp, (IMUChar) impl->data.v_uint32);
        case IM_TYPE_BOOL:
            return im_stream_put_bool (sp, (IMBool) impl->data.v_int32);
        case IM_TYPE_INT16:
            return im_stream_put_int16 (sp, impl->data.v_int16);
        case IM_TYPE_UINT16:
            return im_stream_put_uint16 (sp, impl->data.v_uint16);
        case IM_TYPE_INT32:
            return im_stream_put_int32 (sp, impl->data.v_int32);
        case IM_TYPE_UINT32:
            return im_stream_put_uint32 (sp, impl->data.v_uint32);
        case IM_TYPE_INT64:
            return im_stream_put_int64 (sp, impl->data.v_int64);
        case IM_TYPE_UINT64:
            return im_stream_put_uint64 (sp, impl->data.v_uint64);
        case IM_TYPE_DOUBLE:
            return im_stream_put_double (sp, impl->data.v_double);
        case IM_TYPE_C_STRING:
            return im_stream_put_c_string (sp, (IMChar *)impl->data.v_pointer, (IMSize) (-1));
        case IM_TYPE_POINTER:
            /* Don't support pointer */
            return im_stream_put_void (sp);
        default: 
            if (IM_TYPE_IS_OBJECT(impl->type))
                return im_stream_put_object (sp, impl->data.v_pointer);
            else
                return im_stream_put_void (sp);
    }
    return TRUE;
}

IMBool
__im_value_impl_deserialize (IMValueImpl *impl, IMStream *sp)
{
    IMType type;

    type = im_stream_get_data_type (sp);

    switch (type) {
        case IM_TYPE_INVALID:
            return FALSE;
        case IM_TYPE_VOID:
            {
                if (!im_stream_get_void (sp))
                    return FALSE;
                im_value_impl_clear (impl);
            }
            break;
        case IM_TYPE_CHAR:
            {
                IMChar val;
                if (!im_stream_get_char (sp, &val))
                    return FALSE;
                im_value_impl_set_char (impl, val);
            }
            break;
        case IM_TYPE_UCHAR:
            {
                IMUChar val;
                if (!im_stream_get_uchar (sp, &val))
                    return FALSE;
                im_value_impl_set_uchar (impl, val);
            }
            break;
        case IM_TYPE_BOOL:
            {
                IMBool val;
                if (!im_stream_get_bool (sp, &val))
                    return FALSE;
                im_value_impl_set_bool (impl, val);
            }
            break;
        case IM_TYPE_INT16:
            {
                IMInt16 val;
                if (!im_stream_get_int16 (sp, &val))
                    return FALSE;
                im_value_impl_set_int16 (impl, val);
            }
            break;
        case IM_TYPE_UINT16:
            {
                IMUInt16 val;
                if (!im_stream_get_uint16 (sp, &val))
                    return FALSE;
                im_value_impl_set_uint16 (impl, val);
            }
            break;
        case IM_TYPE_INT32:
            {
                IMInt32 val;
                if (!im_stream_get_int32 (sp, &val))
                    return FALSE;
                im_value_impl_set_int32 (impl, val);
            }
            break;
        case IM_TYPE_UINT32:
            {
                IMUInt32 val;
                if (!im_stream_get_uint32 (sp, &val))
                    return FALSE;
                im_value_impl_set_uint32 (impl, val);
            }
            break;
        case IM_TYPE_INT64:
            {
                IMInt64 val;
                if (!im_stream_get_int64 (sp, &val))
                    return FALSE;
                im_value_impl_set_int64 (impl, val);
            }
            break;
        case IM_TYPE_UINT64:
            {
                IMUInt64 val;
                if (!im_stream_get_uint64 (sp, &val))
                    return FALSE;
                im_value_impl_set_uint64 (impl, val);
            }
            break;
        case IM_TYPE_DOUBLE:
            {
                IMDouble val;
                if (!im_stream_get_double (sp, &val))
                    return FALSE;
                im_value_impl_set_double (impl, val);
            }
            break;
        case IM_TYPE_C_STRING:
            {
                IMChar *str;
                IMSize  length;
                length = im_stream_get_data_size (sp);
                if (!length) return FALSE;
                str = im_malloc (length + 1);
                if (!str) return FALSE;
                if (!im_stream_get_c_string (sp, str, length+1)) {
                    im_free (str);
                    return FALSE;
                }
                str [length] = 0;
                im_value_impl_take_c_string (impl, str);
            }
            break;
        case IM_TYPE_POINTER:
            /* Don't support pointer */
            return FALSE;
        default: 
            {
                IMPointer val;
                if (!IM_TYPE_IS_OBJECT(type))
                    return FALSE;
                val = im_object_new (type);
                if (!val) return FALSE;
                if (!im_stream_get_object (sp, val)) {
                    im_object_unref (val);
                    return FALSE;
                }
                im_value_impl_set_object (impl, val);
            }
    }

    return TRUE;
}

/*
vi:ts=4:nowrap:ai:expandtab
*/
